<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>const命令</title>
</head>
<body>
    <script>
        const PI = 3.12; // 只读的常量
        
        const a; // 声明和赋值必须一起，否则报错

        if(true){
            const b = 12; // const 和 let 一样，只在声明的块有效
        }

        console.log(c); // 报错
        const c = 12; // 和 let 一样，存在暂时性死区；声明前引用报错

        if(true){
            const d = 12; // 和 let 一样，不会提升
        }

        var message = "Hello!";
        let age = 25;
        const message = "Goodbye!"; // 报错
        const age = 30; // 报错 
        // 和 let 一样，不能重复声明
        /* const 和 let 拥有的同样的特征：
            1. 只在它指定的块有效
            2. 都有暂时性死区
            3. 没有提升
            4. 不能重复声明
        */

        /// 1. const 实际上保证的，并不是变量的值不得改动，而是变量指向的那个 内存地址所保存的数据 不得改动
        /// 2. 对于简单数据类型(数字，字符串，布尔值)：值就保存在变量指向的那个内存地址，因此等同于常量
        /// 3. 对于复合类型(主要为数组和对象)：const只能保证这个指针是固定的（即总是指向另一个固定的地址）
        //解析3： 
            const foo = {}
            foo.f = '12';
            foo.g = 0;
            foo = {} // 报错 固定的地址

            const a = [];
            a.push('Hello'); // 可执行
            a.length = 0;    // 可执行
            a = ['Dave'];    // 报错 指向了新数组

            /* 将对象冻结，应该使用Object.freeze方法 */
            const foo = Object.freeze({});
            // 非严格模式：foo.href 将不起作用
            // 严格模式下：foo.href 报错
            foo.href = 'wwww'

            /**扩展**/
            // 将对象彻底冻结的函数
            var constantize = (obj) => {
                Object.freeze(obj);
                Object.keys(obj).forEach( (key, i) => {
                    if ( typeof obj[key] === 'object' ) {
                    constantize( obj[key] );
                    }
                });
            };
        /*
        const表示声明的是常量,和let 一样也是块级作用域 
        1.const 不能重复声明 
        2.声明同时需要赋值 
        3.不能重复赋值 
        4.声明的是对象的话,可以修改对象的内容 
        5.声明的变量不会覆盖window 上面的变量
        */
        const val; // 语法错误,常量未初始化
        const value = 1;
        if(true){
            //作用域不同可以声明,let 可以置换为const
            let value = 1;
        }
        value = 2; //语法错误,不能重复赋值 

        const obj = {};
        obj.xx = "xx";//可以修改对象的内容
        obj = 1;//错误,不能修改obj 的绑定

    </script>
</body>
</html>